#include <assert.h>
#include <string.h>
#include "tcp_connect.h"
using namespace std;
typedef struct {
	uv_write_t req;
	uv_buf_t buf;
} write_req_t;

tcp_connect::tcp_connect(uv_stream_t* stream) :_stream(stream)
{
	_bufptr = (char*)malloc(_bufsize);
	assert(_bufptr);
	_bfreestream=true;
}
tcp_connect::tcp_connect()
{
	_bufptr = (char*)malloc(_bufsize);
	assert(_bufptr);	
}

tcp_connect::~tcp_connect()
{
	if (_bufptr){
		printf("free _bufptr %p\n", _bufptr);
		free (_bufptr); _bufptr =nullptr;
	}	
}

void tcp_connect::process_on_close(uv_handle_t* handle)
{
	free(handle);
	_close_cb(this);
}
void tcp_connect::process_read_bytes(const uv_buf_t* buf, ssize_t nread)
{
	_conn_rd_cb(this, buf->base, nread);
}
void internal_on_write(uv_write_t* req, int status)
{
	tcp_connect* client = (tcp_connect*)req->data;
	client->process_write_return(req, status);
}

void internal_on_close(uv_handle_t* handle) {
	tcp_connect* conn = (tcp_connect*)handle->data;
	conn->process_on_close(handle);	
}

void internal_on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
{
	printf("internal_on_read\n");
	tcp_connect* conn = (tcp_connect*)(handle->data);
	if (nread < 0)
	{
		uv_close((uv_handle_t*)handle, internal_on_close);
	}
	else
	{
		conn->process_read_bytes(buf, nread);
	}
}


void tcp_connect::write_bytes(char* buf, size_t bsize)
{
	write_req_t *req = (write_req_t*)malloc(sizeof(write_req_t));
	char* byteBuf = new char[bsize];
	memcpy(byteBuf, buf, bsize);
	req->buf = uv_buf_init(byteBuf, bsize);
	uv_write((uv_write_t*)req, _stream, &req->buf, 1, internal_on_write);
}
void internal_on_alloc_buf(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
	tcp_connect* client = (tcp_connect*)handle->data;
	client->process_buf_alloc(buf);
}

void tcp_connect::process_buf_alloc(uv_buf_t* buf)
{
	buf->base = _bufptr;
	buf->len = _bufsize;
}

void tcp_connect::process_write_return(uv_write_t* req, int status)
{
	uv_read_start(req->handle, internal_on_alloc_buf, internal_on_read);
	write_req_t* wreq = (write_req_t*)req;
	free(wreq->buf.base);
	free(wreq);
}



void tcp_connect::close()
{	
	//uv_read_stop(_stream);
	if (0==uv_is_closing((uv_handle_t*)_stream))
	{		
		uv_close((uv_handle_t*)_stream, internal_on_close);
	}
}